import os
import csv
import random
import time
import signal
import platform
import winreg
import requests
import zipfile
import subprocess
import pyautogui
import json
from datetime import datetime
from selenium import webdriver
from selenium.webdriver.edge.service import Service
from selenium.webdriver.edge.options import Options

# ===== 配置参数 =====
CSV_PATH = r'C:\Users\Devin\Desktop\python\data\comments_updated_20250801_194942_cleaned.csv'
csv_dir = os.path.dirname(CSV_PATH)
STATE_FILE = os.path.join(csv_dir, 'progress_state.json')
follow_max = 20
daily_follow_limit = 200  # 日关注上限

# ===== 全局变量 =====
driver = None
current_line = 0
today_follow_count = 0

# ===== 编码检测 =====
def detect_file_encoding(file_path: str) -> str:
    encodings = ['utf-8-sig', 'gb18030', 'gbk', 'utf-8']
    for enc in encodings:
        try:
            with open(file_path, 'rb') as f:
                f.read(2048).decode(enc)
            return enc
        except UnicodeDecodeError:
            continue
    print('[警告] 所有编码尝试失败，默认使用 gbk')
    return 'gbk'

# ===== EdgeDriver 自动下载 =====
def get_edge_version():
    for key_path in [
        r"Software\Microsoft\Edge\BLBeacon",
        r"SOFTWARE\Microsoft\EdgeUpdate"
    ]:
        try:
            with winreg.OpenKey(winreg.HKEY_CURRENT_USER, key_path) as key:
                return winreg.QueryValueEx(key, "version")[0]
        except Exception:
            try:
                with winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, key_path) as key:
                    return winreg.QueryValueEx(key, "version")[0]
            except Exception:
                continue
    return None

def download_edgedriver(version):
    arch = "win64" if platform.machine().endswith('64') else "win32"
    url = f"https://msedgedriver.azureedge.net/{version}/edgedriver_{arch}.zip"
    driver_dir = os.path.join(os.path.expanduser("~"), "auto_edgedriver")
    os.makedirs(driver_dir, exist_ok=True)
    zip_path = os.path.join(driver_dir, "edgedriver.zip")
    driver_path = os.path.join(driver_dir, "msedgedriver.exe")

    if os.path.exists(driver_path):
        return driver_path

    print(f"正在下载 EdgeDriver {version} for {arch}...")
    try:
        r = requests.get(url, stream=True, timeout=30)
        r.raise_for_status()
        with open(zip_path, "wb") as f:
            for chunk in r.iter_content(8192):
                f.write(chunk)
        with zipfile.ZipFile(zip_path, 'r') as z:
            z.extractall(driver_dir)
        os.remove(zip_path)
        return driver_path
    except Exception as e:
        print(f"下载失败: {e}")
        return None

def auto_get_edgedriver_path():
    version = get_edge_version()
    if not version:
        raise Exception("无法获取 Edge 浏览器版本")
    driver_path = download_edgedriver(version)
    if not driver_path:
        raise Exception("EdgeDriver 下载失败")
    return driver_path

# ===== 辅助函数 =====
def click_follow_button():
    pyautogui.click(1880, 399)
    print("已点击关注按钮 1880,399")

def random_delay(a=3.14, b=6.39):
    t = random.uniform(a, b)
    print(f"随机延迟 {t:.2f}s")
    time.sleep(t)

def save_state():
    today = datetime.now().strftime("%Y%m%d")
    state = {
        'current_line': current_line,
        'daily_state': {
            'date': today,
            'count': today_follow_count
        }
    }
    with open(STATE_FILE, 'w') as f:
        json.dump(state, f)
    print(f"状态已保存: 当前行 {current_line}, 今日关注 {today_follow_count}")

def load_state():
    global today_follow_count
    if not os.path.exists(STATE_FILE):
        print("⭕ 状态文件不存在，将从头开始处理")
        return 0

    try:
        with open(STATE_FILE) as f:
            state = json.load(f)
        saved_date = state.get('daily_state', {}).get('date', '')
        today = datetime.now().strftime("%Y%m%d")
        if saved_date == today:
            today_follow_count = state.get('daily_state', {}).get('count', 0)
        else:
            today_follow_count = 0
            print(f"检测到新的一天({today})，重置今日关注计数")
        return state.get('current_line', 0)
    except:
        print("状态文件损坏，将从头开始")
        today_follow_count = 0
        return 0

# ===== 主 CSV 处理 =====
def process_csv():
    global current_line, today_follow_count

    current_line = load_state()
    print(f"从行号 {current_line} 开始处理, 今日已关注 {today_follow_count}/{daily_follow_limit}")

    file_encoding = detect_file_encoding(CSV_PATH)
    print(f"检测到文件编码：{file_encoding}")

    with open(CSV_PATH, 'r', encoding=file_encoding, newline='') as f:
        reader = csv.reader(f)
        header = next(reader)
        rows = [r for r in reader if r]

    total = len(rows)
    if total == 0:
        print("CSV 为空！")
        return

    print(f"共 {total} 行数据")

    follow_count = 0

    while current_line < total and follow_count < follow_max:
        if today_follow_count >= daily_follow_limit:
            print(f"⚠️ 今日关注已达上限 {daily_follow_limit}，跳过处理")
            save_state()
            time.sleep(5)
            continue

        row = rows[current_line]
        user_link = row[-1] if row else ""
        if not user_link.strip():
            print(f"行 {current_line} 链接为空，跳过")
            current_line += 1
            save_state()
            continue

        print(f"\n处理行 {current_line+1}/{total}：{user_link}")

        try:
            driver.get(user_link)
            random_delay()
            click_follow_button()
            follow_count += 1
            today_follow_count += 1
            print(f"操作完成！当前关注 {follow_count}/{follow_max}, 今日关注 {today_follow_count}/{daily_follow_limit}")
        except Exception as e:
            print(f"操作过程中出现异常: {e}")
        finally:
            current_line += 1
            save_state()
            random_delay()

    print("🎉 任务完成！")

# ===== 信号/清理 =====
def signal_handler(sig, frame):
    print("\n⚠️  检测到中断信号，正在保存状态...")
    save_state()
    try:
        if driver:
            driver.quit()
    except:
        pass
    print("安全退出")
    exit(0)

def clean_browser():
    try:
        subprocess.run(["taskkill", "/F", "/IM", "msedge.exe"],
                       stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
    except:
        pass

# ===== 主程序入口 =====
if __name__ == "__main__":
    signal.signal(signal.SIGINT, signal_handler)
    signal.signal(signal.SIGTERM, signal_handler)
    clean_browser()

    try:
        driver_path = auto_get_edgedriver_path()
    except Exception as e:
        print(f"自动下载失败: {e}")
        driver_path = r"C:\Users\Devin\.cache\selenium\msedgedriver\win64\136.0.3240.47\msedgedriver.exe"
        print(f"使用备选路径: {driver_path}")

    user_data = os.path.expanduser("~") + r"\AppData\Local\Microsoft\Edge\User Data"
    options = Options()
    options.add_argument(f"--user-data-dir={user_data}")
    options.add_argument("--profile-directory=Default")
    options.add_argument("--ignore-certificate-errors")
    options.add_argument("--ignore-ssl-errors")
    options.add_argument("--disable-features=SSLCommonCrypto")
    service = Service(executable_path=driver_path)
    driver = webdriver.Edge(service=service, options=options)
    driver.maximize_window()
    print("浏览器已最大化")

    try:
        process_csv()
    except Exception as e:
        print(f"运行中发生错误: {e}")
    finally:
        try:
            driver.quit()
        except:
            pass